﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using AllenalaMente.State;
using Microsoft.Phone.Controls;
using System.Windows.Media.Imaging;

namespace AllenalaMente.Games
{
    /// <summary>
    /// Gestisce il flusso di Gioco chiamando in sequenza Intro, Game e Recap per le 4 categorie di gioco
    /// ed infine il Final Recap Screen
    /// </summary>
    public partial class GamePage : PhoneApplicationPage
    {
        private GameState gameState;

        // Pages 
        private GameIntro gameIntro;
        private UserControl game;
        private GameRecap gameRecap;
        private GamesFinalRecap gamesFinalRecap;

        private Random random;

        private GamesId currentGameId;
        private int currentGameIndex = 0;

        public GamePage()
        {
            InitializeComponent();

            gameState = GameStateManager.GetState();

            random = new Random();

            InitializeGame();
        }

        #region Metodi

        private void InitializeGame()
        {
            gameIntro = new GameIntro();
            gameIntro.buttonClose.Click += new RoutedEventHandler(introClose);            
            ContentPanel.Children.Add(gameIntro);

           
            PageTitle.Text = Locale.Strings.Intro;

            LoadGame();
        }

        /// <summary>
        /// Carica il prossimo gioco settando la variabile currentGameId
        /// </summary>
        private void LoadGame()
        {
            GameInfo currentGameInfo = null;

            currentGameInfo = gameState.GamesList[gameState.chosenGames[currentGameIndex]];
            currentGameId = currentGameInfo.gameId;

            //PageTitle.Text = currentGameId.ToString().Substring(3);
            setImageGame((GameCategories)currentGameIndex);

            abc.Visibility = Visibility.Visible;

            // Setta Istruzioni e Immagine del prossimo gioco nella pagina di Intro
            gameIntro.setDescriptionText(currentGameId.ToString().Substring(3), currentGameInfo.istructions, currentGameInfo.istructionImagePaths, currentGameInfo.tutorialImagePaths);
        }

        /// <summary>
        /// Avvia il gioco indicato da currentGameId
        /// </summary>
        private void StartGame()
        {
            // Start the correct game based on the id
            switch (currentGameId)
            {
                case GamesId.Me_Lost:
                    game = new Lost.Lost();
                    setImageGame(GameCategories.Memory);
                    PageTitle.Text = "Lost";
                    break;
                case GamesId.Ma_Bubbles:
                    game = new Bubbles.Bubbles();
                    setImageGame(GameCategories.Math);
                    PageTitle.Text = "Bubbles";
                    break;
                case GamesId.Re_Target:
                    game = new Target.Target();
                    setImageGame(GameCategories.Reflex);
                    PageTitle.Text = "Target";
                    break;
                case GamesId.Re_Sword:
                    game = new Sword.Sword();
                    setImageGame(GameCategories.Reflex);
                    PageTitle.Text = "Sword";
                    break;
                case GamesId.Lo_Puzzle:
                    game = new NewPuzzle.NewPuzzle();
                    setImageGame(GameCategories.Logic);
                    PageTitle.Text = "Puzzle";
                    break;
                case GamesId.Ma_Calculator:
                    game = new Calculator.Calculator();
                    setImageGame(GameCategories.Math);
                    PageTitle.Text = "Calculator";
                    break;
                case GamesId.Re_Quake:
                    game = new Quake.Quake();
                    setImageGame(GameCategories.Reflex);
                    PageTitle.Text = "Quake";
                    break;
                case GamesId.Ma_Blocks:
                    game = new Blocks.Blocks();
                    setImageGame(GameCategories.Math);
                    PageTitle.Text = "Blocks";
                    break;
                case GamesId.Me_Recall:
                    game = new Recall.Recall();
                    setImageGame(GameCategories.Memory);
                    PageTitle.Text = "Recall";
                    break;
                case GamesId.Re_Selection:
                    game = new Selection.Selection();
                    setImageGame(GameCategories.Reflex);
                    PageTitle.Text = "Selection";
                    break;
                case GamesId.Me_Exchanges:
                    game = new Exchanges.Exchanges();
                    setImageGame(GameCategories.Memory);
                    PageTitle.Text = "Exchanges";
                    break;
                case GamesId.Lo_Flux:
                    game = new Flux.Flux();
                    setImageGame(GameCategories.Logic);
                    PageTitle.Text = "Flux";
                    break;
                case GamesId.random:
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// Imposta l'icona della categoria del gioco
        /// </summary>
        /// <param name="category">La categoria del gioco</param>
        private void setImageGame(GameCategories category)
        {
            string imageName = category.ToString();

            if (imageName == "Title") imageName = "Testa";
            if (imageName == "Recap") imageName = "Cup";

            string path = "/AllenalaMente;component/Assets/Images/UI/" + imageName + ".png";

            // Carica Immagine
            Uri uri = new Uri(path, UriKind.RelativeOrAbsolute);
            ImageSource img = new System.Windows.Media.Imaging.BitmapImage(uri);
            imageGame.SetValue(Image.SourceProperty, img);
        }

        #endregion

        #region Eventi

        // Fine Intro
        private void introClose(object sender, RoutedEventArgs e)
        {
            gameIntro.buttonClose.Click -= introClose;
            ContentPanel.Children.Remove(gameIntro);
            gameIntro = null;

            // Inizializza il gioco e lo lancia
            StartGame();

            ((GameInterface)game).GameEnd += gameEnd;
            ContentPanel.Children.Add(game);
        }

        // Fine Gioco
        private void gameEnd(object sender, GameEventArgs e)
        {
            e.id = currentGameId; // Memorizzo l'id del gioco
            e.index = AllenalaMente.State.GameStateManager.getIndex(currentGameId); // Memorizzo l'indice del gioco relativo alla lista di appartenenza

            // Prepara il lancio del gioco successivo
            ((GameInterface)game).GameEnd -= gameEnd;
            currentGameIndex++;

            ContentPanel.Children.Remove(game);
            game = null;

            // Lancia il recap screen
            gameRecap = new GameRecap(e);
            gameRecap.buttonClose.Click += new RoutedEventHandler(recapClose);
            ContentPanel.Children.Add(gameRecap);

            PageTitle.Text = Locale.Strings.Recap;

            scores[currentGameIndex - 1] = e; // Memorizza il risultato ottenuto nel gioco appena concluso
        }

        // Elenco locale dei risultati ottenuti
        private GameEventArgs[] scores = new GameEventArgs[] { null, null, null, null };

        // Fine Recap
        private void recapClose(object sender, RoutedEventArgs e)
        {
            // Alla chiusura del recap screen lancia il gioco successivo,
            // a meno che non abbia finito la serie dei 4 giochi
            // in tal caso lancia il recap conclusivo
            gameRecap.buttonClose.Click -= recapClose;
            ContentPanel.Children.Remove(gameRecap);
            gameRecap = null;

            // Incrementa l'indice per il gioco successivo
            int gamesNumber = gameState.chosenGames.Count(g => g != -1);

            if (currentGameIndex == gamesNumber)
            {
                if (gameState.gameMode == GameMode.Normal)
                {
                    // Lancia il recap screen finale
                    gamesFinalRecap = new GamesFinalRecap(scores);
                    gamesFinalRecap.buttonClose.Click += finalRecapClose;
                    gamesFinalRecap.buttonClose2.Click += finalRecapClose;

                    ContentPanel.Children.Add(gamesFinalRecap);

                    PageTitle.Text = Locale.Strings.FinalRecap;
                    setImageGame(GameCategories.Recap);
                }
                else
                {
                    // Practice Mode
                    ContentPanel.Children.Remove(gamesFinalRecap);
                    gamesFinalRecap = null;

                    NavigationService.GoBack(); // Torna la Menu Principale
                }
            }
            else
            {
                InitializeGame();
            }
        }

        // Fine Final Recap
        private void finalRecapClose(object sender, RoutedEventArgs e)
        {
            if (gamesFinalRecap.isAnimated)
            {
                gamesFinalRecap.SkipAnimation();
            }
            else
            {
                gamesFinalRecap.buttonClose.Click -= recapClose;
                gamesFinalRecap.buttonClose2.Click -= recapClose;
                ContentPanel.Children.Remove(gamesFinalRecap);
                gamesFinalRecap = null;

                NavigationService.GoBack(); // Torna la Menu Principale
            }
        }

        #endregion

        // DEBUG

        /// <summary>
        /// Simula Fine-Vittoria del gioco creando un risultato casuale
        /// </summary>
        private void buttonWin_Click(object sender, RoutedEventArgs e)
        {
            if (gameIntro != null) return;

            // Fa finire il gioco
            GameEventArgs gea = new GameEventArgs();
            gea.reason = GameCloseReason.Timeout;
            gea.score = random.Next(1, 10) * 200;
            gea.giuste = random.Next(1, 10);
            gea.sbagliate = random.Next(1, 10);

            gameEnd(this, gea);
        }

    }
}
